package probe.sound.core;

import static java.lang.Math.exp;
import static java.lang.Math.log;

public class ProbeSyn implements Producer {
  public static void main(String[] args) {
    Syn play = new SynPlay();
    //Syn play = new SynWave( "/tmp/wow.wav" );
    
    play.setProducer( new ProbeSyn() );
    play.setTimeDelay( T * N * 2 );
    
    play.run();
    
    System.out.println( "OK" );
  }
  
  private static double K = log( 2.0 ) / 12.0;
  private static double A0 = 440;
  
  private static double z(double n) {
    return A0 * exp( n * K );
  }
  
  private static final double T = 0.4;
  private static final double L = 0.6;
  
  //private static final double N = 32 + 32;
  //private static final double N = 8 + 8 + 8 + 8 + 8;
  
  private static final double N = 32 + 32 + 8 + 8 + 8 + 8 + 8;
  
  //private static final double N = 8 + 8 + 8 + 8;
  
  @Override
  public void produce(Value value, double t1) {
    while (t1 > T * N) {
      t1 -= T * N;
    }
    
    double x = 0;
    
    int i = 0;
    
    //@formatter:off
    {
      double t = t1 - i++ * 8*T;
      if (in( t, 0,   1   )) x += beep( t, 7 );
      if (in( t, 1,   2   )) x += beep( t, 15 ) + beep( t, 0, 0.3 );
      if (in( t, 2,   3   )) x += beep( t, 14 );
      if (in( t, 3,   4   )) x += beep( t, 12 );
      if (in( t, 4,   5   )) x += beep( t, 11 );
      if (in( t, 5,   6   )) x += beep( t, 12 ) + beep( t, 0, 0.3 );
      if (in( t, 6,   6.5 )) x += beep( t, 14 );
      if (in( t, 6.5, 7   )) x += beep( t, 15 );
      if (in( t, 7,   8   )) x += beep( t, 12 );
    }
    
    {
      double t = t1 - i++ * 8*T;
      if (in( t, 0,   1   )) x += beep( t,  7 );
      if (in( t, 1,   2   )) x += beep( t, 19 ) + beep( t, 0, 0.3 );
      if (in( t, 2,   3   )) x += beep( t, 17 );
      if (in( t, 3,   4   )) x += beep( t, 15 );
      if (in( t, 4,   5   )) x += beep( t, 14 );
      if (in( t, 5,   6   )) x += beep( t, 15 ) + beep( t, 0, 0.3 );
      if (in( t, 6,   6.5 )) x += beep( t, 15 );
      if (in( t, 6.5, 7   )) x += beep( t, 17 );
      if (in( t, 7,   8   )) x += beep( t, 19 );
    }
    
    {
      double t = t1 - i++ * 8*T;
      if (in( t, 0,   1   )) x += beep( t,  7 );
      if (in( t, 1,   2.5 )) x += beep( t, 20 ) + beep( t, -5, 0.3 );
      if (in( t, 2.5, 3   )) x += beep( t, 19 );
      if (in( t, 3,   4.5 )) x += beep( t, 17 );
      if (in( t, 4.5, 5   )) x += beep( t, 15 );
      if (in( t, 5,   5.5 )) x += beep( t, 14 );
      if (in( t, 5.5, 6   )) x += beep( t, 15 );
      if (in( t, 6,   8   )) x += beep( t, 17 );
    }
    
    {
      double t = t1 - i++ * 8*T;
      if (in( t, 0, 1 )) x += beep( t, 20 );
      if (in( t, 1, 2 )) x += beep( t, 19 ) + beep( t, -5, 0.3 );
      if (in( t, 2, 3 )) x += beep( t, 17 );
      if (in( t, 3, 4 )) x += beep( t, 15 );
      if (in( t, 4, 5 )) x += beep( t, 17 );
      if (in( t, 5, 8 )) x += beep( t, 14 ) + beep( t, -5, 0.3 );
    }
    
    /////////////////////////////////////////////////////////////////////
    
    {
      double t = t1 - i++ * 8*T;
      if (in( t, 0,   1   )) x += beep( t, 7 );
      if (in( t, 1,   2   )) x += beep( t, 15 ) + beep( t, 0, 0.3 );
      if (in( t, 2,   3   )) x += beep( t, 14 );
      if (in( t, 3,   4   )) x += beep( t, 12 );
      if (in( t, 4,   5   )) x += beep( t, 11 );
      if (in( t, 5,   6   )) x += beep( t, 12 ) + beep( t, 0, 0.3 );
      if (in( t, 6,   6.5 )) x += beep( t, 14 );
      if (in( t, 6.5, 7   )) x += beep( t, 15 );
      if (in( t, 7,   8   )) x += beep( t, 12 );
    }
    
    {
      double t = t1 - i++ * 8*T;
      if (in( t, 0,   1   )) x += beep( t,  7 );
      if (in( t, 1,   2   )) x += beep( t, 19 ) + beep( t, 0, 0.3 );
      if (in( t, 2,   3   )) x += beep( t, 17 );
      if (in( t, 3,   4   )) x += beep( t, 15 );
      if (in( t, 4,   5   )) x += beep( t, 14 );
      if (in( t, 5,   6   )) x += beep( t, 15 ) + beep( t, 0, 0.3 );
      if (in( t, 6,   6.5 )) x += beep( t, 15 );
      if (in( t, 6.5, 7   )) x += beep( t, 17 );
      if (in( t, 7,   8   )) x += beep( t, 19 );
    }
    
    {
      double t = t1 - i++ * 8*T;
      if (in( t, 0,   1   )) x += beep( t,  7 );
      if (in( t, 1,   2.5 )) x += beep( t, 20 ) + beep( t, -5, 0.3 );
      if (in( t, 2.5, 3   )) x += beep( t, 19 );
      if (in( t, 3,   4.5 )) x += beep( t, 17 );
      if (in( t, 4.5, 5   )) x += beep( t, 15 );
      if (in( t, 5,   5.5 )) x += beep( t, 14 );
      if (in( t, 5.5, 6   )) x += beep( t, 15 );
      if (in( t, 6,   8   )) x += beep( t, 17 );
    }
    
    {
      double t = t1 - i++ * 8*T;
      if (in( t, 0, 1 )) x += beep( t, 20 );
      if (in( t, 1, 2 )) x += beep( t, 19 ) + beep( t, -5, 0.3 );
      if (in( t, 2, 3 )) x += beep( t, 17 );
      if (in( t, 3, 4 )) x += beep( t, 14 );
      if (in( t, 4, 5 )) x += beep( t, 15 );
      if (in( t, 5, 8 )) x += beep( t, 12 ) + beep( t, -5, 0.3 );
    }
    
    /////////////////////////////////////////////////////////////////////////////
    /////////////////////////////////////////////////////////////////////////////
    
    {
      double t = t1 - i++ * 8*T;
      
      if (in( t, 0,     0.5  )) x += beep( t, 22 );
      if (in( t, 0.55,  1.5  )) x += beep( t, 22 ) + beep( t, 0, 0.3 );
      if (in( t, 1.5,   2.5  )) x += beep( t, 12 );
      if (in( t, 2.5,   3.5  )) x += beep( t, 16 );
      if (in( t, 3.5,   4.44 )) x += beep( t, 22 );
      if (in( t, 4.5,   5    )) x += beep( t, 22 ) + beep( t, 0, 0.3 );
      if (in( t, 5,     5.5  )) x += beep( t, 20 );
      if (in( t, 5.5,   6    )) x += beep( t, 19 );
      if (in( t, 6,     6.5  )) x += beep( t, 20 );
      if (in( t, 6.5,   8    )) x += beep( t, 24, 1.2 ) + beep( t, 20, 0.3 ) + beep( t, 17, 0.3 ) ;
    }
    {
      double t = t1 - i++ * 8*T;
      
      if (in( t, 0,     0.5  )) x += beep( t, 20 );
      if (in( t, 0.55,  1.5  )) x += beep( t, 20 ) + beep( t, 0, 0.3 );
      if (in( t, 1.5,   2.5  )) x += beep( t, 10 );
      if (in( t, 2.5,   3.5  )) x += beep( t, 14 );
      if (in( t, 3.5,   4.44 )) x += beep( t, 20 );
      if (in( t, 4.5,   5    )) x += beep( t, 20 ) + beep( t, 3, 0.3 );
      if (in( t, 5,     5.5  )) x += beep( t, 19 );
      if (in( t, 5.5,   6    )) x += beep( t, 18 );
      if (in( t, 6,     6.5  )) x += beep( t, 19 );
      if (in( t, 6.5,   8    )) x += beep( t, 22, 1.2 ) + beep( t, 19, 0.3 ) + beep( t, 15, 0.3 ) ;
    }
    
    {
      double t = t1 - i++ * 8*T;
      
      if (in( t, 0,    0.9 )) x += beep( t, 19 );
      if (in( t, 1,    1.5 )) x += beep( t, 17 ) + beep( t, 5, 0.3 );
      if (in( t, 1.5,  2   )) x += beep( t, 19 );
      if (in( t, 2,    2.5 )) x += beep( t, 20 );
      if (in( t, 2.5,  3   )) x += beep( t, 24 );
      if (in( t, 3,    3.5 )) x += beep( t, 29 );
      if (in( t, 3.5,  4   )) x += beep( t, 27 );
      if (in( t, 4,    4.5 )) x += beep( t, 26 );
      if (in( t, 4.5,  4.9   )) x += beep( t, 24 );
      if (in( t, 5,    6.4 )) x += beep( t, 24, 1.2 ) + beep( t, 7, 0.5 ) ;
      if (in( t, 6.5,  8   )) x += beep( t, 23, 1.2 ) + beep( t, 17, 0.3 ) + beep( t, 14, 0.3 ) ;
    }
    
    {
      double t = t1 - i++ * 8*T;
      
      if (in( t, 0,    0.9 )) x += beep( t, 19, 0 );
      if (in( t, 1,    1.5 )) x += beep( t, 17 ) + beep( t, 5, 0.3 );
      if (in( t, 1.5,  2   )) x += beep( t, 19 );
      if (in( t, 2,    2.5 )) x += beep( t, 20 );
      if (in( t, 2.5,  3   )) x += beep( t, 24 );
      if (in( t, 3,    3.5 )) x += beep( t, 29 );
      if (in( t, 3.5,  4   )) x += beep( t, 27 );
      if (in( t, 4,    4.5 )) x += beep( t, 26 );
      if (in( t, 4.5,  4.9   )) x += beep( t, 24 );
      if (in( t, 5,    6.4 )) x += beep( t, 24, 1.2 ) + beep( t, 7, 0.5 ) ;
      if (in( t, 6.5,  8   )) x += beep( t, 23, 1.2 ) + beep( t, 17, 0.3 ) + beep( t, 14, 0.3 ) ;
      if (in( t, 8,    9.5 )) x += beep( t, 24, 1.2 ) + beep( t, 19, 0.3 ) + beep( t, 15, 0.3 ) ;
    }
    //@formatter:on
    
    value.left = x;
    value.right = x;
  }
  
  private boolean in(double t, double from, double to) {
    return ((from * T) < t) && (t <= (to * T));
  }
  
  private double beep(double t, int n) {
    return beep( t, n, 1 );
  }
  
  private double beep(double t, int n, double l) {
    return L * Math.sin( z( n ) * 2 * Math.PI * t ) * l;
  }
}
